﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace SpiritAlight.SceneManagement
{
    /// <summary>
    /// シーンの移行状態を表す列挙型
    /// </summary>
    public enum SceneState
    {
        Active,
        TransitionOn,
        TransitionOff,
        Hidden,
    }

    public abstract class AScene
    {
        /// <summary>
        /// シーンのカラーフィルタ。
        /// アルファ値はシーンの移行状態で変化する。
        /// </summary>
        Color sceneColor = new Color(255, 255, 255, 255);



        #region プロパティ

        /// <summary>
        /// 現在のシーンの状態を行う。
        /// </summary>
        public SceneState NowState
        {
            get { return nowState; }
            protected set 
            {
                switch (value)
                {
                    case SceneState.Active:
                        transitionPosition = 1.0f;
                        break;
                    case SceneState.Hidden:
                        transitionPosition = 0.0f;
                        break;
                    default:
                        nowState = value;
                        break;
                }
            }
        }
        SceneState nowState;

        /// <summary>
        /// この画面が属しているマネージャーを取得します。
        /// </summary>
        //public SceneManager SceneManager
        //{
        //    get { return sceneManager; }
        //}
        //SceneManager sceneManager;

        /// <summary>
        /// 状態がHiddenへ移行したとき
        /// trueであればシーンを削除する。
        /// </summary>
        public bool IsRemove
        {
            get { return isRemove; }
            set { isRemove = value; }
        }
        bool isRemove = false;


        /// <summary>
        /// シーン移行のを完了するまでにかかる時間(秒)を設定する。
        /// </summary>
        public float TransitionTime
        {
            get { return transitionTime; }
            set { transitionTime = value; }
        }
        float transitionTime = 1.0f;

        /// <summary>
        /// シーンの移行状態を0～1であらわす。1がActive、0がHidden
        /// </summary>
        public float TransitionPosition
        {
            get { return transitionPosition; }
        }
        float transitionPosition;

        /// <summary>
        /// シーンのアルファ値。
        /// シーンの状態によって変化する。
        /// </summary>
        public Byte SceneAlpha
        {
            get { return sceneColor.A; }
            protected set { sceneColor.A = value; }
        }

        protected Color SceneColor
        {
            get { return sceneColor; }
        }

        /// <summary>
        /// フォーカスが当たっている際の処理を保存する。
        /// 処理はInitialize中で設定する。
        /// </summary>
        public Action OnFocus
        {
            get { return onFocus; }
        }
        protected Action onFocus;

        #endregion


        #region メソッド

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="Manager">シーンを登録するマネージャ</param>
        public AScene(SceneState state)
        {
            NowState = state;
        }

        /// <summary>
        /// シーンの初期化を行うメソッド。
        /// </summary>
        public virtual void Initialize() { onFocus = () => { }; }

        /// <summary>
        /// シーン中に必要なリソースをロードする。
        /// </summary>
        public virtual void LoadContents() { }

        /// <summary>
        /// シーンのアップデートを行う。
        /// シーンがどの状態であっても実行される。
        /// </summary>
        public virtual void Update()
        {
            switch (nowState)
            {
                case SceneState.Active          : UpdateActive();       break;
                case SceneState.TransitionOn    : UpdateTransitionOn(); break;
                case SceneState.TransitionOff   : UpdateTransitionOff();break;
                case SceneState.Hidden          : UpdateHidden();       break;
            }
        }

        /// <summary>
        /// シーンがActiveの状態のとき呼び出されるメソッド。
        /// オーバーライドし、Active時の処理を記述する。
        /// </summary>
        protected virtual void UpdateActive() { }

        /// <summary>
        /// シーンがTransitionOnのときに呼び出されるメソッド。
        /// 必要に応じてオーバーライドし、TransitionOn時の処理を記述する。
        /// </summary>
        protected virtual void UpdateTransitionOn()
        {
            //Activeへ移行中
            //時間から変更する数値を割り出し、シーンのポジションを移動
            transitionPosition += 1.0f / 60.0f / transitionTime;
            
            //ポジションが1以上になったらシーンをActiveへ完全移行
            if (transitionPosition >= 1.0f)
            {
                transitionPosition = 1.0f;
                sceneColor.A = sceneColor.R = sceneColor.G = sceneColor.B = 255;

                nowState = SceneState.Active;
            }

            //ポジションからアルファ値を計算し、代入。
            sceneColor.A = sceneColor.R = sceneColor.G = sceneColor.B = (Byte)(255.0f * transitionPosition);
        }

        /// <summary>
        /// シーンがTransitionOffのときに呼び出されるメソッド。
        /// 必要に応じてオーバーライドし、TransitionOff時の処理を記述する。
        /// </summary>
        protected virtual void UpdateTransitionOff()
        {
            //Hiddenへ移行中
            //時間から変更する数値を割り出し、シーンのポジションを移動
            transitionPosition -= 1.0f / 60.0f / transitionTime;

            //ポジションが0以下になったらシーンをHiddenへ完全移行
            if (transitionPosition <= 0.0f)
            {
                transitionPosition = 0.0f;
                sceneColor.A = sceneColor.R = sceneColor.G = sceneColor.B = 0;
                nowState = SceneState.Hidden;
                if (isRemove)
                {
                    SceneManager.SceneList.Remove(this);
                }
            }

            //ポジションからアルファ値を計算し、代入。
            sceneColor.A = sceneColor.R = sceneColor.G = sceneColor.B = (Byte)(255.0f * transitionPosition);
        }

        /// <summary>
        /// シーンがHiddenのときに呼び出されるメソッド。
        /// 必要に応じてオーバーライドし、Hidden時の処理を記述する。
        /// </summary>
        protected virtual void UpdateHidden()
        {
            //isRemoveフラグが立っていた場合、このシーンを削除する。
            if (isRemove)
            {
                SceneManager.SceneList.Remove(this);
            }
        }

        

        /// <summary>
        /// 描画処理を行う
        /// </summary>
        public virtual void Draw() { }
        
        /// <summary>
        /// Activeへシーンの移行を開始する。
        /// </summary>
        public void TransOn() { nowState = SceneState.TransitionOn; }

        /// <summary>
        /// Hiddenへシーンの移行を開始する。
        /// </summary>
        public void TransOff() { nowState = SceneState.TransitionOff; }



        #endregion
    }
}
